package system.report;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Map;
import java.util.Vector;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;

import au.com.bytecode.opencsv.CSVWriter;
import framework.core.DBConnection;
import framework.core.StringUtil;

public class ReportExporterUtils {

	private static final String TEMP = "temp";

	private static final String COMMA = "\t";

	public static void writeCSV_ReportSeventh(Vector vec, String warehouseCode,
			String month, String title, String fileName, String title1,
			HttpServletRequest request, HttpServletResponse response,
			String start, String end, DBConnection con) {

		ServletOutputStream out = null;
		try {
			/** 创建Sheet 开始 */
			int size = vec.size();// 获得结果集大小
			boolean needNew = true;// 标示变量 当需要创建一个新的sheet页的时候 值为true
			String category_code1 = null;// 存储索引i的类别编号
			String category_code2 = null;// 存储索引i+1的类别编号
			String category_name = null;// 当前的类别名称
			short index = 2; // 当前所在行号
			double totalMonthStorageMoney = 0;// 一个sheet中用来统计合计
			double totalMonthStorageCount = 0;// 一个sheet中用来统计合计
			double totalInCount = 0;// 一个sheet中用来统计合计
			double totalInMoney = 0;// 一个sheet中用来统计合计
			double totalOutCount = 0;// 一个sheet中用来统计合计
			double totalOutMoney = 0;// 一个sheet中用来统计合计
			double totalMonthEndCount = 0;// 一个sheet中用来统计合计
			double totalMonthEndMoney = 0;// 一个sheet中用来统计合计


			CSVWriter tWriter = null;

			String folderPath = mkDir(request);
			for (int k = 0; k < size; k++) {

				Map map1 = (Map) vec.get(k);
				Map map2 = null;
				category_name = map1.get("CATE_NAME") == null ? ""
						: (String) map1.get("CATE_NAME");// 获取当前索引的类型名称
				if (size > 1 && k != size - 1) {
					map2 = (Map) vec.get(k + 1);// 如果集合大于2并且当前不是最后一位索引
				}
				// 获取下一位索引的对象
				if (map2 != null) {
					category_code1 = (String) map1.get("CATEGORY_CODE");
					category_code2 = (String) map2.get("CATEGORY_CODE");
				}
				// 创建 新文件 当条件满足时
				if (needNew) {

					tWriter = new CSVWriter(new FileWriter(new File(folderPath+"/"+category_name+".csv"), true));
					// 写标题行
					String[] tTitleAry = new String[]{"", "", "", "", title1, "", "", "", "", "", "", "", "", "", ""};
					tWriter.writeNext(tTitleAry);
					// 写日期行
					String[] tTimeAry = new String[]{"", "", "", "", "", "", "", "", "", "产品分类:" + category_name
							+ "     " + start + " 至 " + end, "", "", "", "", ""};
					tWriter.writeNext(tTimeAry);

					// 表头行
					String[] tReportTitleAry = new String[] {"产品编码", "自编码", "产品名称", "规格", "型号", "品牌", "单位", "单价",
							"期初数量", "期初金额", "入库数量", "入库金额", "领出数量", "领出金额", "期末数量", "期末金额"};
					tWriter.writeNext(tReportTitleAry);
					needNew = false;
				}


				double productMonthMoney = 0;// 用来统计单行数据的
				double productMonthCount = 0;// 用来统计单行数据的
				double productInCount = 0;// 用来统计单行数据的
				double productInMoney = 0;// 用来统计单行数据的
				double productOutCount = 0;// 用来统计单行数据的
				double productOutMoney = 0;// 用来统计单行数据的
				double monthEndCount = 0;// 用来统计单行数据的
				double monthEndMoney = 0;// 用来统计单行数据的

				/** 获取本行中的数字数据 */
				productMonthCount = Double.parseDouble((String) map1.get("INIT_COUNT"));
				productMonthMoney = Double.parseDouble((String) map1.get("INIT_MONEY"));
				productInCount = Double.parseDouble((String) map1.get("IN_COUNT"));
				productInMoney = Double.parseDouble((String) map1.get("IN_MONEY"));
				productOutCount = Double.parseDouble((String) map1.get("OUT_COUNT"));
				productOutMoney = Double.parseDouble((String) map1.get("OUT_MONEY"));
				monthEndCount = Double.parseDouble((String) map1.get("FINAL_COUNT"));
				monthEndMoney = Double.parseDouble((String) map1.get("FINAL_MONEY"));
				/** 获取本行中的数字数据 */

				/** 为单元格填充相应数据 */
				String[] tContentAry = new String[]{
						COMMA + getMapValue(map1, "CONCENTRICITY_CODE"),
						COMMA + getMapValue(map1, "APEP_CODE"),
						COMMA + getMapValue(map1, "NAME"),
						COMMA + getMapValue(map1, "SPEC"),
						COMMA + getMapValue(map1, "MODEL"),
						COMMA + getMapValue(map1, "PRODUCT_BRAND"),
						COMMA + getMapValue(map1, "PRODUCT_UNIT"),
						COMMA + StringUtil.showCount(String.valueOf(Double.parseDouble(getMapValue(map1, "PRODUCT_PRICE")))),
						COMMA + StringUtil.showCount(String.valueOf(productMonthCount)),
						COMMA + StringUtil.showPrice(String.valueOf(productMonthMoney)),
						COMMA + StringUtil.showCount(String.valueOf(productInCount)),
						COMMA + StringUtil.showPrice(String.valueOf(productInMoney)),
						COMMA + StringUtil.showCount(String.valueOf(productOutCount)),
						COMMA + StringUtil.showPrice(String.valueOf(productOutMoney)),
						COMMA + StringUtil.showCount(String.valueOf(monthEndCount)),
						COMMA + StringUtil.showPrice(String.valueOf(monthEndMoney))
				};
				tWriter.writeNext(tContentAry);

				/** 为单元格填充相应数据 */

				/** 累加本行数据 */
				totalInCount += productInCount;
				totalInMoney += productInMoney;
				totalOutCount += productOutCount;
				totalOutMoney += productOutMoney;
				totalMonthStorageCount += productMonthCount;
				totalMonthStorageMoney += productMonthMoney;
				totalMonthEndCount += monthEndCount;
				totalMonthEndMoney += monthEndMoney;
				index++;
				/** 累加本行数据 */

				// 当发现 索引i与索引i+1的类别不同时
				if (!category_code1.equals(category_code2)) {
					needNew = true;
				}
				// 当发现本索引是集合最后一位时
				if (k == size - 1) {
					needNew = true;
				}
				// 如果本页行数大于2 并且 下一个索引的类别和本索引类别不同 结束本页 并填充本页合计
				if (index > 2 && needNew) {

					String[] tTotalAry = new String[] {
							"",
							"",
							"",
							"",
							"",
							"合计:",
							"",
							"",
							StringUtil.showCount(String.valueOf(totalMonthStorageCount)),
							StringUtil.showPrice(String.valueOf(totalMonthStorageMoney)),
							StringUtil.showCount(String.valueOf(totalInCount)),
							StringUtil.showPrice(String.valueOf(totalInMoney)),
							StringUtil.showCount(String.valueOf(totalOutCount)),
							StringUtil.showPrice(String.valueOf(totalOutMoney)),
							StringUtil.showCount(String.valueOf(totalMonthEndCount)),
							StringUtil.showPrice(String.valueOf(totalMonthEndMoney))
					};
					tWriter.writeNext(tTotalAry);

					/** sheet统计数据回零 */
					index = 2; // 当前所在行号
					totalMonthStorageMoney = 0;
					totalMonthStorageCount = 0;
					totalInCount = 0;
					totalInMoney = 0;
					totalOutCount = 0;
					totalOutMoney = 0;
					totalMonthEndCount = 0;
					totalMonthEndMoney = 0;
					/** sheet统计数据回零 */


					// 写文件
					tWriter.close();
				}
			}

			byte[] tZippedFile = zipFile(folderPath);

			/** 输出EXCEL文件 开始 */
			fileName = fileName + ".zip";
			response.setContentType("application/octet-stream; charset=UTF-8");
			response.addHeader("Content-disposition", "filename=" + fileName);
			//response.setCharacterEncoding("UTF-8");
			out = response.getOutputStream();
			out.write(tZippedFile, 0, tZippedFile.length);

			out.flush();
			//out.close();
			/** 输出EXCEL文件 结束 */

			deleteDir(folderPath);
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {

					e.printStackTrace();
				}
			}
		}

	}


	private static String getMapValue(Map map , String key) {
		Object value = map.get(key);
		if(value == null) {
			return "";
		}

		return (String)value;
	}


	private static byte[] zipFile(String folderPath) throws Exception {
		ByteArrayOutputStream tByteArrayOutputStream = new ByteArrayOutputStream();

		//		ZipOutputStream tZipOutputStream = new ZipOutputStream(new FileOutputStream(new File("d://dddddd.zip")));
		ZipArchiveOutputStream tZipArchiveOutputStream = new ZipArchiveOutputStream(tByteArrayOutputStream);

		//		CompressorOutputStream tZipOutputStream = new CompressorStreamFactory().createCompressorOutputStream(CompressorStreamFactory.GZIP, tByteArrayOutputStream);

		File tFile = new File(folderPath);
		String[] tTmpFileList = tFile.list();

		File temp = null;
		for(int i=0; i<tTmpFileList.length; i++) {
			String filePath ;
			if(folderPath.endsWith(File.separator)) {
				filePath = folderPath + tTmpFileList[i];
			} else {
				filePath = folderPath + File.separator + tTmpFileList[i];
			}

			temp = new File(filePath);
			if(temp.isFile()) {
				ZipArchiveEntry tArchiveEntry = new ZipArchiveEntry(temp, temp.getName());
				tArchiveEntry.setSize(temp.length());
				tZipArchiveOutputStream.putArchiveEntry(tArchiveEntry);
				FileInputStream tFileInputStream = new FileInputStream(temp);
				int readByte = 512;
				byte[] buffer = new byte[readByte];
				while((readByte = tFileInputStream.read(buffer)) > 0) {
					tZipArchiveOutputStream.write(buffer, 0, readByte);
				}
				tZipArchiveOutputStream.flush();
				tFileInputStream.close();
				tZipArchiveOutputStream.closeArchiveEntry();
			}

		}

		tZipArchiveOutputStream.flush();

		tZipArchiveOutputStream.finish();
		tByteArrayOutputStream.flush();
		tZipArchiveOutputStream.setEncoding("UTF-8");
		byte[] tByteArray = tByteArrayOutputStream.toByteArray();



		tZipArchiveOutputStream.close();
		tByteArrayOutputStream.close();

		//FileOutputStream fileout = new FileOutputStream(new File("d:\\eeee.zip"));
		//fileout.write(tByteArray, 0, tByteArray.length);
		//fileout.close();

		return tByteArray;
	}

	private static String mkDir(HttpServletRequest request) {
		String sessionId = request.getSession().getId();
		String tRealPath = request.getRealPath("/");
		String tFolderPath = tRealPath + "/" + TEMP + "/" + sessionId;
		File tFile = new File(tFolderPath);
		if(tFile != null && !tFile.exists()) {
			tFile.mkdir();
		}

		return tFolderPath;

	}

	private static void deleteDir(String folderPath) {
		File tFile = new File(folderPath);

		if(tFile.exists()) {
			deleteAllFile(folderPath);
			tFile.delete();
		}
	}

	private static void deleteAllFile(String folderPath) {
		File file = new File(folderPath);

		if(!file.exists()) {
			return;
		}

		if(!file.isDirectory()) {
			return;
		}

		String[] tempList = file.list();

		File temp = null;

		for(int i=0; i<tempList.length; i++) {
			if(folderPath.endsWith(File.separator)) {
				temp = new File(folderPath + tempList[i]);
			} else {
				temp = new File(folderPath + File.separator + tempList[i]);
			}

			if(temp.isFile()) {
				temp.delete();
			}

			if(temp.isDirectory()) {
				deleteAllFile(folderPath + "/" + tempList[i]);
				deleteDir(folderPath + "/" + tempList[i]);
			}
		}
	}
}
